﻿#include "mblock.h"
#include "debug.h"

/**
 * @brief 初始化内存块管理器
 * @param mblock 需要初始化的内存块管理器
 * @param mem 分配空闲内存的起始地址
 * @param blk_size 每一块空闲内存的大小
 * @param cnt 空闲内存块的数量
 * @param type 锁的类型
 */
net_err_t mblock_init(mblock_t *mblock, void *mem, int blk_size, int cnt, nlocker_type_t type)
{
    if (!mblock || !mem)
    {
        DBG_ERROR(DBG_MBLOCK_LEVEL, "mblock or mem is null in mblock init!");
        return NET_ERR_SYS;
    }

    // 对内存的操作使我敬畏
    nlist_init(&mblock->free_list);
    uint8_t *buf = (uint8_t *)mem;

    for (int i = 0; i < cnt; ++i, buf += blk_size)
    {
        nlist_node_t *block = (nlist_node_t *)buf;
        nlist_node_init(block);
        nlist_insert_last(&mblock->free_list, block);
    }

    nlocker_init(&mblock->locker, type);
    if (NLOCKER_THREAD == type)
    {
        mblock->alloc_sem = sys_sem_create(cnt);
        if (SYS_SEM_INVALID == mblock->alloc_sem)
        {
            DBG_ERROR(DBG_MBLOCK_LEVEL, "sem create failed!");
            nlocker_destroy(&mblock->locker);
            return NET_ERR_SYS;
        }
    }

    return NET_ERR_OK;
}

/**
 * @brief 通过内存管理器分配内存
 * @param mblock 内存管理器地址
 * @param ms 分配内存等待时间
 */
void *mblock_alloc(mblock_t *mblock, int ms)
{
    if (!mblock)
    {
        DBG_ERROR(DBG_MBLOCK_LEVEL, "mblock is null!");
        return 0;
    }

    // 无线程控制 或者 等待时间为0 直接获取内存 否则 通过信号量控制
    if (ms < 0 || mblock->locker.type == NLOCKER_NONE)
    {
        nlocker_lock(&mblock->locker);
        int count = mblock->free_list.count;
        if (!count)
        {
            nlocker_unlock(&mblock->locker);
            return NULL;
        }
        else
        {
            nlist_node_t *block = nlist_remove_first(&mblock->free_list);
            nlocker_unlock(&mblock->locker);
            return block;
        }
    }
    else
    {
        if (sys_sem_wait(mblock->alloc_sem, ms) < 0)
        {
            // 超时返回空
            return NULL;
        }
        else
        {
            nlocker_lock(&mblock->locker);
            nlist_node_t *block = nlist_remove_first(&mblock->free_list);
            nlocker_unlock(&mblock->locker);
            return block;
        }
    }
}

/**
 * @brief 获取内存管理器中的空闲内存数量
 */
int mblock_free_block_cnt(mblock_t *mblock)
{
    if (!mblock)
    {
        DBG_ERROR(DBG_MBLOCK_LEVEL, "mblock is null!");
        return 0;
    }

    nlocker_lock(&mblock->locker);
    int count = mblock->free_list.count;
    nlocker_unlock(&mblock->locker);
    return count;
}

/**
 * @brief 内存块的释放
 */
void mblock_free(mblock_t *mblock, void *block)
{
    if (!mblock)
    {
        DBG_ERROR(DBG_MBLOCK_LEVEL, "mblock is null!");
        return;
    }

    nlocker_lock(&mblock->locker);
    nlist_insert_last(&mblock->free_list, block);
    nlocker_unlock(&mblock->locker);

    // 如果是用于线程间的锁，别忘了处理信号量
    if (mblock->locker.type == NLOCKER_THREAD)
    {
        sys_sem_notify(mblock->alloc_sem);
    }
}

/**
 * @brief 内存管理器的销毁
 */
void mblock_destroy(mblock_t *mblock)
{
    if (!mblock)
    {
        DBG_ERROR(DBG_MBLOCK_LEVEL, "mblock is null!");
        return;
    }

    // 针对不同的类型进行不同的处理
    if (NLOCKER_THREAD == mblock->locker.type)
    {
        sys_sem_free(mblock->alloc_sem);
        nlocker_destroy(&mblock->locker);
    }
}